/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
 */
package td.server.util;

import java.util.Date;

import td.domain.Draft;
import td.domain.ListCachedObject;
import td.domain.Thinker;
import td.domain.Thought;
import td.domain.util.IdCache;
import td.server.dao.ObjectifyDao;
import td.server.dao.ThinkerDao;
import td.server.dao.ThoughtDao;
import td.server.dao.ThoughtVersionDao;

import com.google.inject.Inject;

/**
 * Object responsible for handling all of versioning logic.
 * 
 * @author Artem Shamsutdinov
 * 
 */
public class Versioner {

	public static final int FIRST_VERSION_SEQUENCE = 1;

	@Inject
	ThinkerDao thinkerDao;
	@Inject
	ThoughtDao thoughtDao;
	@Inject
	ObjectifyDao<IdCache> idCacheDao;
	@Inject
	ThoughtVersionDao thoughtVersionDao;

	/**
	 * Creates a new version or modifies an existing one and maintains related
	 * state in the owning Thought and Thinker objects.
	 * 
	 * @param text
	 *            The text of the new version
	 * @param versionSequence
	 *            The sequence of the version being maintained/created.
	 * @param thought
	 *            The thought to which the maintained/created version belongs
	 *            to.
	 * @param thinker
	 *            The thinker to which the maintained/created version belongs
	 *            to.
	 * @param publish
	 *            Should the version be published?
	 * @param now
	 *            Time of modification/creation of the version.
	 * @param thoughtVersion
	 *            The version being modified (null if created).
	 * @param isOlderThanNewestPublished
	 *            Is this the newest version or an older one?
	 * @param isInitialPublishing
	 *            Is this the first time a version for this thought being
	 *            published?
	 * @return
	 */
	public Long maintainVersions(String text, int versionSequence,
			Thought thought, Thinker thinker, boolean publish, Date now,
			Draft thoughtVersion, boolean isOlderThanNewestPublished,
			boolean isInitialPublishing) {
		return null;
		// FIXME: add this back in and figure out how to deal with Ref in GWT
		// boolean existingThoughtVersion = true;
		// if (thoughtVersion == null) {
		// thoughtVersion = createNewThoughtVersion(thought, text, now, publish,
		// versionSequence, thinker);
		// thought.setHighestSequence(thoughtVersion.getSequence());
		// existingThoughtVersion = false;
		// }
		// thought.setLastUpdatedDate(now);
		// Ref<IdCache> recentVersionIds =
		// thought.getRecentUnpublishedVersionIds();
		// Ref<IdCache> recentThoughtIds =
		// thinker.getRecentUnpublishedThoughtIds();
		// if (publish) {
		// recentVersionIds = thought.getRecentPublishedVersionIds();
		// recentThoughtIds = thinker.getRecentPublishedThoughtIds();
		//
		// if (isOlderThanNewestPublished) {
		// thought.setLastPublishedOlderVersionDate(now);
		// // Update thinker
		// thinker.setLastPublishedOlderVersionDate(now);
		// thinker.setLastPublishedOlderVersionId(thoughtVersion.getId());
		// } else {
		// thought.setHighestPublishedSequence(thoughtVersion.getSequence());
		// thought.setPublishedDate(now);
		// // Update thinker
		// thinker.setLastPublishedDate(now);
		// thinker.setLastPublishedVersionId(thoughtVersion.getId());
		// }
		// if (isInitialPublishing) {
		// thought.setPublished(true);
		// }
		// if (existingThoughtVersion) {
		// thoughtVersion.setIsPublished(true);
		// thoughtVersion.setPublishedDate(now);
		// thoughtVersionDao.put(thoughtVersion);
		// }
		// thinkerDao.put(thinker);
		// }
		// thoughtDao.put(thought);
		// maintainAddingOfObjects(recentVersionIds.get(), thoughtVersion,
		// thoughtVersionDao);
		//
		// if (Versioner.FIRST_VERSION_SEQUENCE == versionSequence
		// || isInitialPublishing) {
		// maintainAddingOfObjects(recentThoughtIds.get(), thought, thoughtDao);
		// }
		//
		// return thoughtVersion.getId();
	}

	private <T extends ListCachedObject> void maintainAddingOfObjects(
			IdCache recentObjectIds, T object, ObjectifyDao<T> dao) {
		Long rolledOffObjectId = recentObjectIds.add(object.getId());
		idCacheDao.put(recentObjectIds);

		if (rolledOffObjectId != null) {
			@SuppressWarnings("unchecked")
			T rolledOffObject = dao.get(rolledOffObjectId);
			rolledOffObject.setDroppedOffLists(true);
			dao.put(rolledOffObject);
		}
	}

	private Draft createNewThoughtVersion(Thought thought, String text,
			Date now, boolean publish, Integer sequence, Thinker thinker) {
		Draft thoughtVersion = new Draft();
		thoughtVersion.setCreatedDate(now);
		thoughtVersion.setThoughtId(thought.getId());
		thoughtVersion.setThinkerId(thinker.getId());
		thoughtVersion.setText(text);
		thoughtVersion.setIsPublished(publish);
		if (publish) {
			thoughtVersion.setPublishedDate(now);
		}
		thoughtVersion.setSequence(sequence);
		thoughtVersionDao.putNow(thoughtVersion);

		return thoughtVersion;
	}
}
